package com.open.capacity.paper.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.common.auth.details.LoginAppUser;
import com.open.capacity.common.exception.service.ServiceException;
import com.open.capacity.common.model.*;
import com.open.capacity.common.util.RateUtil;
import com.open.capacity.common.web.PageResult;
import com.open.capacity.common.web.Result;
import com.open.capacity.paper.dao.*;
import com.open.capacity.paper.feign.UserFeignClient;
import com.open.capacity.paper.service.PaperService;
import com.open.capacity.paper.vo.PaperRecordCountVo;
import com.open.capacity.paper.vo.PaperRecordInfoVo;
import com.open.capacity.paper.vo.PaperVo;
import com.open.capacity.paper.vo.QuestionVo;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * @author liangd
 * @since 2021-02-01 14:37
 */
@Service
@Slf4j
public class PaperServiceImpl extends ServiceImpl<PaperDao, Paper> implements PaperService {

    @Autowired
    private PaperDao paperDao;

    @Autowired
    private PaperQuestionDao paperQuestionDao;

    @Autowired
    private RateTypeDao rateTypeDao;

    @Autowired
    private PaperRecordDao paperRecordDao;

    @Autowired
    private PaperRecordInfoDao paperRecordInfoDao;

    @Autowired
    private SuggestDao suggestDao;

    @Resource
    private UserFeignClient userFeignClient;

    @Override
    public PageResult<PaperVo> getPapers(Map<String, Object> params) throws ServiceException {
        try {
            //设置分页信息，分别是当前页数和每页显示的总记录数
            if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null) {
                PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);
            }
            Long userid = MapUtils.getLong(params, "userid");
            List<Paper> list = paperDao.findList(params);
            List<PaperRecord> paperRecords = new LambdaQueryChainWrapper<>(paperRecordDao).eq(PaperRecord::getUserid, userid).list();
            List<PaperVo> paperVoList = list.stream().map(paper -> {
                PaperVo paperVo = new PaperVo();
                BeanUtils.copyProperties(paper, paperVo);
                SysRole sysRole = userFeignClient.findById(paper.getFacegp().longValue());
                paperVo.setFacegpStr(sysRole.getName());
                LoginAppUser user = userFeignClient.findByUsername(paper.getPublis());
                paperVo.setPublisStr(user.getNickname());
                LoginAppUser respdt = userFeignClient.findByUsername(paper.getRespdt());
                paperVo.setRespdtStr(respdt.getNickname());
                RateType rateType = rateTypeDao.getRateType(paper.getRtcode());
                paperVo.setRtcodeStr(rateType.getRtname());
                if (paperRecords.size() > 0) {
                    for (PaperRecord paperRecord : paperRecords) {
                        if (paper.getPapeid().equals(paperRecord.getPapeid())) {
                            paperVo.setStateStr("已完成");
                        }
                    }
                }
                return paperVo;
            }).collect(Collectors.toList());

            PageInfo<PaperVo> pageInfo = new PageInfo<>(paperVoList);
            PageInfo<Paper> paperInfo = new PageInfo<>(list);
            return PageResult.<PaperVo>builder().data(pageInfo.getList()).code(0).count(paperInfo.getTotal()).build();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ServiceException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updatePaper(Paper paper) throws ServiceException {
        try {
            paper.setUpdtim(new Date());
            int i = paperDao.updateById(paper);
            if (i > 0) {
                return Result.succeed("更新成功");
            }
            return Result.failed("更新失败");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result savePaper(Paper paper) throws ServiceException {
        try {
            paper.setCretim(new Date());
            paper.setStatus(1);
            int i = paperDao.insert(paper);
            if (i > 0) {
                return Result.succeed("新增成功");
            }
            return Result.failed("新增失败");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Result findById(Integer papeid) throws ServiceException {
        try {
            Paper paper = paperDao.selectById(papeid);
            return Result.succeed(paper, "");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deletePaper(Integer papeid) throws ServiceException {
        try {
            List<PaperQuestion> list = new LambdaQueryChainWrapper<>(paperQuestionDao).eq(PaperQuestion::getPapeid, papeid).list();
            if (list.size() > 0) {
                return Result.failed("该问卷与问题已关联，请先移除关系，在进行操作！");
            }
            Paper paper = paperDao.selectById(papeid);
            paper.setStatus(2);
            paperDao.updateById(paper);
            return Result.succeed("操作成功");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Result getQuestionAndOption(Integer papeid) throws ServiceException {
        try {
            List<Question> questionList = paperDao.findQuestionByPaperId(papeid);
            List<QuestionVo> collect = questionList.stream().map(question -> {
                QuestionVo questionVo = new QuestionVo();
                BeanUtils.copyProperties(question, questionVo);
                List<Option> optionList = paperDao.findOptionByQuestionId(question.getQuesid());
                questionVo.setOptionList(optionList);
                return questionVo;
            }).collect(Collectors.toList());
            return Result.succeedWith(collect, 0, "");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result savePaperData(PaperRecordInfoVo paperRecordInfoVo) throws ServiceException {
        try {
            Paper paper = paperDao.selectById(paperRecordInfoVo.getPapeid());
            String psrate = RateUtil.convertPscore(paper.getRtcode(), paperRecordInfoVo.getPscore());
            //问卷记录
            PaperRecord paperRecord = PaperRecord.builder().papeid(paperRecordInfoVo.getPapeid()).userid(paperRecordInfoVo.getUserid())
                    .pscore(paperRecordInfoVo.getPscore()).fintim(new Date()).psrate(psrate).build();
            //问卷记录详情
            List<PaperRecordInfo> infoList = new ArrayList<>();
            List<Integer> quesids = paperRecordInfoVo.getQuesids();
            List<Integer> optnids = paperRecordInfoVo.getOptnids();
            for (int i = 0; i < quesids.size(); i++) {
                PaperRecordInfo recordInfo = PaperRecordInfo.builder().papeid(paperRecordInfoVo.getPapeid()).userid(paperRecordInfoVo.getUserid())
                        .quesid(quesids.get(i)).optnid(optnids.get(i)).build();
                infoList.add(recordInfo);
            }
            //建议
            Suggest suggest = Suggest.builder().papeid(paperRecordInfoVo.getPapeid()).userid(paperRecordInfoVo.getUserid())
                    .contex(paperRecordInfoVo.getContex()).sugper(paperRecordInfoVo.getSugper()).status(1)
                    .cretim(new Date()).respdt(paperRecordInfoVo.getRespdt()).build();

            paperRecordDao.insert(paperRecord);
            //更新称号
            List<PaperRecordCountVo> countVos = paperRecordDao.getPaperPieData(paperRecord.getPapeid());
            double avgscr = getAvgScore(countVos);
            LoginAppUser appUser = userFeignClient.findByUsername(paperRecordInfoVo.getRespdt());
            Set<SysRole> roles = userFeignClient.findRolesByUserId(appUser.getId());
            for (SysRole sysRole : roles) {
                userFeignClient.updateTitleOfRoleCodeByUserId(appUser.getId(), avgscr, sysRole.getCode());
            }
            paperRecordInfoDao.insertBatch(infoList);
            int i = suggestDao.insert(suggest);
            return i > 0 ? Result.succeed("保存成功") : Result.failed("保存失败");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updatePaperData(PaperRecordInfoVo paperRecordInfoVo) throws ServiceException {
        try {
            Paper paper = paperDao.selectById(paperRecordInfoVo.getPapeid());
            String psrate = RateUtil.convertPscore(paper.getRtcode(), paperRecordInfoVo.getPscore());
            Integer papeid = paperRecordInfoVo.getPapeid();
            Long userid = paperRecordInfoVo.getUserid();
            List<Integer> quesids = paperRecordInfoVo.getQuesids();
            List<Integer> optnids = paperRecordInfoVo.getOptnids();
            //问卷记录
            List<PaperRecord> paperRecords = paperRecordDao.findPaperRecord(papeid, userid);
            PaperRecord paperRecord = paperRecords.get(0);
            paperRecord.setPscore(paperRecordInfoVo.getPscore());
            paperRecord.setPsrate(psrate);
            paperRecordDao.updateByPaperIdAndUserId(paperRecord);
            //建议
            Suggest suggest = suggestDao.selectByPaperIdAndUserId(papeid, userid);
            suggest.setContex(paperRecordInfoVo.getContex());
            suggest.setUpdtim(new Date());
            suggestDao.updateByPaperIdAndUserId(suggest);
            //更新称号
            List<PaperRecordCountVo> countVos = paperRecordDao.getPaperPieData(paperRecord.getPapeid());
            double avgscr = getAvgScore(countVos);
            LoginAppUser appUser = userFeignClient.findByUsername(paperRecordInfoVo.getRespdt());
            Set<SysRole> roles = userFeignClient.findRolesByUserId(appUser.getId());
            for (SysRole sysRole : roles) {
                userFeignClient.updateTitleOfRoleCodeByUserId(appUser.getId(), avgscr, sysRole.getCode());
            }
            //问卷记录详情
            int result = 0;
            for (int i = 0; i < optnids.size(); i++) {
                result = paperRecordInfoDao.updateByIds(papeid, userid, quesids.get(i), optnids.get(i));
            }
            return result > 0 ? Result.succeed("修改成功") : Result.failed("修改失败");
        } catch (ServiceException e) {
            throw new ServiceException(e);
        }

    }

    @Override
    public Result findPaperRecord(Map<String, Object> params) throws ServiceException {
        try {
            Integer papeid = MapUtils.getInteger(params, "papeid");
            Long userid = MapUtils.getLong(params, "userid");
            List<PaperRecord> recordList = paperRecordDao.findPaperRecord(papeid, userid);
            return recordList.size() > 0 ? Result.failed("该问卷您以及填写过了") : Result.succeed("");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ServiceException(e);
        }
    }

    @Override
    public Result findPaperInfo(Integer papeid, Long userid) throws ServiceException {
        try {
            List<PaperRecord> paperRecords = paperRecordDao.findPaperRecord(papeid, userid);
            PaperRecord paperRecord = paperRecords.get(0);
            List<PaperRecordInfo> paperRecordInfos = paperRecordInfoDao.findPaperRecordInfo(papeid, userid);
            Suggest suggest = suggestDao.selectByPaperIdAndUserId(papeid, userid);

            List<Integer> quesids = new ArrayList<>();
            List<Integer> optnids = new ArrayList<>();
            for (PaperRecordInfo paperRecordInfo : paperRecordInfos) {
                quesids.add(paperRecordInfo.getQuesid());
                optnids.add(paperRecordInfo.getOptnid());
            }
            PaperRecordInfoVo paperRecordInfoVo = PaperRecordInfoVo.builder().papeid(papeid).userid(userid)
                    .optnids(optnids).quesids(quesids).contex(suggest.getContex()).pscore(paperRecord.getPscore())
                    .sugper(suggest.getSugper()).build();

            return Result.succeedWith(paperRecordInfoVo, 0, "");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ServiceException(e);
        }
    }

    @Override
    public Result getPaperPieData(Integer papeid) throws ServiceException {
        try {
            // 转换为百分数
            List<Map<String, Object>> pieData = new ArrayList<>();
            List<PaperRecordCountVo> paperRecordCountVos = paperRecordDao.getPaperPieData(papeid);
            long count = 0L;
            for (PaperRecordCountVo paperRecordCountVo : paperRecordCountVos) {
                count += paperRecordCountVo.getPcount();
            }
            double dCount = count;
            for (int i = 0; i < paperRecordCountVos.size(); i++) {
                Long pcount = paperRecordCountVos.get(i).getPcount();
                Map<String, Object> countMap = new HashMap<>();
                countMap.put("name", paperRecordCountVos.get(i).getPsrate());
                countMap.put("y", pcount / dCount);
                countMap.put("sliced", false);
                countMap.put("selected", false);
                if (i == 0) {
                    countMap.put("sliced", true);
                    countMap.put("selected", true);
                }
                pieData.add(countMap);
            }
            return Result.succeed(pieData, "");
        } catch (Exception e) {
            throw new ServiceException(e);
        }

    }

    @Override
    public Result getPaperLinearData(Integer papeid) throws ServiceException {
        try {
            List<PaperRecordCountVo> countVos = paperRecordDao.getPaperPieData(papeid);
            double avgscr = getAvgScore(countVos);
            List<PaperRecordCountVo> collect = countVos.stream().map(paperRecordCountVo -> PaperRecordCountVo.builder()
                    .papeid(paperRecordCountVo.getPapeid()).psrate(paperRecordCountVo.getPsrate())
                    .pcount(paperRecordCountVo.getPcount()).avgscr(avgscr).build()).collect(Collectors.toList());
            return Result.succeed(collect, "");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 获取平均分
     *
     * @param countVos List<PaperRecordCountVo>
     * @return double
     */
    private double getAvgScore(List<PaperRecordCountVo> countVos) {
        long scoreCount = 0L;
        int count = 0;
        for (PaperRecordCountVo countVo : countVos) {
            if (countVo.getPsrate().equals("优秀")) {
                scoreCount += countVo.getPcount() * 5;
            }
            if (countVo.getPsrate().equals("良好")) {
                scoreCount += countVo.getPcount() * 4;
            }
            if (countVo.getPsrate().equals("中等")) {
                scoreCount += countVo.getPcount() * 3;
            }
            if (countVo.getPsrate().equals("继续努力")) {
                scoreCount += countVo.getPcount() * 2;
            }
            if (countVo.getPsrate().equals("不及格")) {
                scoreCount += countVo.getPcount();
            }
            count += countVo.getPcount() * 5;
        }
        double dscoreCount = scoreCount;
        return dscoreCount / count;
    }
}
